home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / nn.zip / OPTIONS.C < prev    next >
C/C++ Source or Header  |  1989-06-28  |  4KB  |  203 lines

  1. /*
  2.  * generic option parsing 
  3.  *
  4.  * (c) Copyright 1988, Kim F. Storm, storm@texas.dk
  5.  */
  6.  
  7. #include "config.h"
  8. #include "options.h"
  9.  
  10. static char **save_argv, *usage_mesg;
  11. static struct option_descr *save_optd;
  12.  
  13. char *program_name(av)
  14. char **av;
  15. {
  16.     char *cp;
  17.     
  18.     /* skip "/path/" part of program name */
  19.     if (cp = strrchr(*av, '/')) 
  20.     return cp + 1;
  21.     else
  22.     return *av;
  23. }
  24.  
  25.     
  26. parse_options(ac, av, envname, options, usage)
  27. int ac;
  28. char **av, *envname;
  29. struct option_descr options[];
  30. char *usage;
  31. {
  32.     register char *cp, opt;
  33.     register struct option_descr *od;
  34.     extern int atoi();
  35.     int files;
  36.     char **names;
  37.     char *envinit;
  38.  
  39.     save_argv = av;
  40.     save_optd = options;
  41.     
  42.     if (options == NULL) return 0;
  43.  
  44.     usage_mesg = usage;
  45.     
  46.     --ac;
  47.     names = ++av;    
  48.     files = 0;
  49.     
  50.     envinit = envname ? getenv(envname) : NULL;
  51.     cp = envinit;
  52.  
  53.  next_option:
  54.     
  55.     if (envinit) {
  56.     while (*cp && isspace(*cp)) cp++;
  57.     if (*cp == '-') {
  58.         cp++;
  59.         goto next_option;
  60.     }
  61.     if (*cp == NUL) {
  62.         envinit = NULL;
  63.         goto next_option;
  64.     }
  65.     } else
  66.     if (cp == NULL || *cp == NUL) {
  67.         if ((cp = *av++) == NULL) {
  68.         *names = NULL;
  69.         return files;
  70.         }
  71.         ac--;
  72.         
  73.         if (*cp != '-') {
  74.         *names++ = cp;
  75.         cp = NULL;
  76.         files++;
  77.         goto next_option;
  78.         }
  79.         
  80.         cp++; /* skip - */
  81.     }
  82.     
  83.     opt = *cp++;
  84.     
  85.     for (od = options; od->option_letter; od++) {
  86.     if (od->option_letter != opt) continue;
  87.     
  88.     switch (od->option_type) {
  89.         
  90.      case 1:    /* BOOL_OPTION */
  91.         
  92.         *((int *)(od->option_address)) = !*((int *)(od->option_address));
  93.         goto next_option;
  94.         
  95.      case 2:    /* STRING_OPTION */
  96.      case 3:    /* OPTIONAL_STRING */
  97.         
  98.         /* -oSTR or -o STR */
  99.         
  100.         while (*cp && isspace(*cp)) cp++;
  101.         
  102.         if (*cp == NUL) {
  103.         if (envinit || ac == 0) {
  104.             if (od->option_type == 3) goto opt_str;
  105.             error("missing string argumet to -%c", opt);
  106.         }
  107.         cp = *av++;
  108.         ac--;
  109.         }
  110.         
  111.         if (od->option_type == 3 && *cp == '-') goto opt_str;
  112.         
  113.         *(od->option_address) = cp;
  114.         
  115.         if (envinit) {
  116.         while (*cp && !isspace(*cp)) cp++;
  117.         if (*cp) *cp++ = NUL;
  118.         } else
  119.         cp = NULL;
  120.         
  121.         goto next_option;
  122.         
  123.      opt_str:
  124.         *(od->option_address) = od->option_default;
  125.         goto next_option;
  126.         
  127.      case 4:
  128.      case 5:
  129.         
  130.         /* -oN or -o N */
  131.         
  132.         while (*cp && isspace(*cp)) cp++;
  133.         
  134.         if (*cp) {
  135.         if (!isdigit(*cp)) {
  136.             if (od->option_type == 5) goto opt_int;
  137.             error("non-numeric argument to -%c", opt);
  138.         }
  139.         } else {
  140.         if (envinit || ac == 0 || !isdigit(**av)) {
  141.             if (od->option_type == 5) goto opt_int;
  142.             error("missing argument to -%c", opt);
  143.         }
  144.         
  145.         cp = *av++;
  146.         ac--;
  147.         }
  148.         *((int *)(od->option_address)) = atoi(cp);
  149.         while (isdigit(*cp)) cp++;
  150.         goto next_option;
  151.         
  152.      opt_int:
  153.         *((int *)(od->option_address)) = (int)(od->option_default);
  154.         goto next_option;
  155.     }
  156.     }
  157.     
  158.     error("unknown option '-%c'", opt);
  159.     /*NOTREACHED*/
  160. }
  161.  
  162.  
  163. static error(message, option_letter)
  164. char *message, option_letter;
  165. {
  166.     char *prog_name = program_name(save_argv);
  167.     
  168.     fprintf(stderr, "%s: ", prog_name);
  169.     fprintf(stderr, message, option_letter);
  170.     fputc('\n', stderr);
  171.  
  172.     fprintf(stderr, "usage: %s", prog_name);
  173.     
  174.     dump_options(1, "");
  175.     dump_options(2, " STR");
  176.     dump_options(3, " [STR]");
  177.     dump_options(4, " NUM");
  178.     dump_options(5, " [NUM]");
  179.         
  180.     if (usage_mesg) fprintf(stderr, usage_mesg);
  181.     fputc(NL, stderr);
  182.  
  183.     nn_exit(9);
  184. }
  185.  
  186. static dump_options(type, tail)
  187. int type;
  188. char *tail;
  189. {
  190.     register struct option_descr *od;
  191.     int any = 0;
  192.     
  193.     for (od = save_optd; od->option_letter; od++) {
  194.     if (od->option_type != type) continue;
  195.     fprintf(stderr, any ? "%c" : " -%c", od->option_letter );
  196.     any++;
  197.     }
  198.     
  199.     if (any && tail && tail[0]) {
  200.     fprintf(stderr, "%s", tail);
  201.     }
  202. }
  203.